package com.xiyuan.smartutils;

import com.xiyuan.smartutils.logging.LogFactory;
import com.xiyuan.smartutils.logging.Logger;
import com.xiyuan.smartutils.seqs.Sequence;

import java.util.Locale;
import java.util.concurrent.*;

/**
 * 线程相关工具类
 *
 * @version v1.0.0 @author lgz 2017-8-27 新建与整理
 */

public final class Threads {
    
    private Threads() {}
    
    private static final Logger logger = LogFactory.getLogger(Threads.class);
    
    /**
     * 获取调用者堆栈对象
     *
     * @return 调用者堆栈
     */
    public static StackTraceElement getInvoker() {
        StackTraceElement[] elems = Thread.currentThread().getStackTrace();
        // 0是Thread本身，1是Threads，2是getInvoker方法的使用者，3才是正主，引入getInvoker使用的调用者
        return elems[3];
    }
    
    /**
     * 获取调用者类名、方法名和行数
     *
     * @return 调用者堆栈字符串
     */
    public static String getInvokerString() {
        StackTraceElement[] elems = Thread.currentThread().getStackTrace();
        StackTraceElement elem = elems[3];
        return new StringBuilder().append("[")
                .append(elem.getClassName())
                .append("]")
                .append("[")
                .append(elem.getMethodName())
                .append("]")
                .append("[第")
                .append(elem.getLineNumber())
                .append("行]")
                .toString();
    }
    
    /**
     * 获取调用者类名、方法名和行数简写
     *
     * @return 调用者堆栈字符串
     */
    public static String getInvokerAbbr() {
        StackTraceElement[] elems = Thread.currentThread().getStackTrace();
        StackTraceElement elem = elems[3];
        String className = StrUtils.removeLeftByLast(elem.getClassName(), ".");
        return new StringBuilder().append("[")
                .append(className)
                .append(".")
                .append(elem.getMethodName())
                .append("(第")
                .append(elem.getLineNumber())
                .append("行)")
                .append("]")
                .toString();
    }
    
    /***********************************************************************************/
    // 新建线程
    /***********************************************************************************/
    
    /**
     * 生成一个新的线程
     *
     * @param runnable 线程运行类
     * @return Thread
     */
    public static Thread newThread(Runnable runnable) {
        return new Thread(runnable);
    }
    
    /**
     * 生成一个新的线程
     *
     * @param runnable 线程运行类
     * @param name     线程名
     * @return Thread
     */
    public static Thread newThread(Runnable runnable, String name) {
        return new Thread(runnable, name);
    }
    
    /**
     * 生成一个新的线程
     *
     * @param runnable 线程运行类
     * @param name     线程名
     * @param sequence 序号
     * @return Thread
     */
    public static Thread newThread(Runnable runnable, String name, int sequence) {
        return new Thread(runnable, name + "-" + sequence);
    }
    
    /**
     * 生成一个新的线程
     *
     * @param runnable 线程运行类
     * @param name     线程名
     * @param sequence 序号表
     * @return Thread
     */
    public static Thread newThread(Runnable runnable, String name, Sequence sequence) {
        return new Thread(runnable, name + "-" + sequence.next());
    }
    
    /**
     * 生成一个新的线程
     *
     * @param group    线程组
     * @param runnable 线程运行类
     * @param sequence 序号
     * @return Thread
     */
    public static Thread newThread(ThreadGroup group, Runnable runnable, int sequence) {
        return new Thread(group, runnable, group.getName() + "-" + sequence);
    }
    
    /**
     * 生成一个新的线程
     *
     * @param group    线程组
     * @param runnable 线程运行类
     * @param sequence 序号表
     * @return Thread
     */
    public static Thread newThread(ThreadGroup group, Runnable runnable, Sequence sequence) {
        return new Thread(group, runnable, group.getName() + "-" + sequence.next());
    }
    
    /***********************************************************************************/
    // 中断线程
    /***********************************************************************************/
    
    /**
     * 忽略线程睡眠时的中断异常，使用时放置到while最下端
     *
     * @param millis 毫秒数
     */
    public static void sleepIgnoreException(long millis) {
        if (millis <= 0) {
            return;
        }
        
        try {
            Thread.sleep(millis);
        }
        catch (InterruptedException e) {
        }
    }
    
    /**
     * 关闭关忽略异常
     */
    public static void closeIgnoreException(AutoCloseable closeable) {
        Closes.closeIgnoreException(closeable);
    }
    
    /**
     * 停止线程池
     * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
     * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
     * 如果仍然超時，則強制退出.
     * 另对在shutdown时线程本身被调用中断做了处理.
     */
    public static void shutdownAndAwaitTermination(ExecutorService pool) {
        if (pool != null && !pool.isShutdown()) {
            pool.shutdown();
            try {
                if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
                    pool.shutdownNow();
                    if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
                        logger.info("Pool did not terminate");
                    }
                }
            }
            catch (InterruptedException ie) {
                pool.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }
    
    /**
     * 打印线程异常信息
     */
    public static void printException(Runnable r, Throwable t) {
        if (t == null && r instanceof Future<?>) {
            try {
                Future<?> future = (Future<?>) r;
                if (future.isDone()) {
                    future.get();
                }
            }
            catch (CancellationException ce) {
                t = ce;
            }
            catch (ExecutionException ee) {
                t = ee.getCause();
            }
            catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
            }
        }
        if (t != null) {
            logger.error(t.getMessage(), t);
        }
    }
}
